package com.w1.security.handler;



import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;


/**
 * 这步的核心是根据getCredentials拿到保存的用户信息
 * 认证执行器
 * @author mingyifan
 * @date 2022-02-24 16:10
 */
@Component
public class AuthProvider implements AuthenticationProvider {
    private UserDetailsService userDetailsService;
    private PasswordEncoder passwordEncoder;

    public AuthProvider(@Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        this.userDetailsService = userDetailsService;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Authentication authenticate(Authentication authentication)  {
        UserDetails userDetails = userDetailsService.loadUserByUsername(String.valueOf(authentication.getCredentials()));
        //转换authentication 认证时会先调用support方法,受支持才会调用,所以能强转
        // 用户名密码校验 具体逻辑
        additionalAuthenticationChecks(userDetails, authentication);
        //构造已认证的authentication
        UsernamePasswordAuthenticationToken authenticatedToken = new UsernamePasswordAuthenticationToken(userDetails, null, new ArrayList<>());
        return authenticatedToken;

    }
    /**
     * 是否支持当前类
     * @return
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    /**
     * 检查密码是否正确
     */
    private void additionalAuthenticationChecks(UserDetails userDetails, Authentication authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            throw new BadCredentialsException("Bad credentials");
        }
        String presentedPassword = authentication.getCredentials().toString();
        if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            throw new BadCredentialsException("Bad credentials");
        }
    }

}
